package com.fz.service.impl;

import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fz.core.FzException;
import com.fz.entity.TPermission;
import com.fz.entity.TUser;
import com.fz.mapper.TUserMapper;
import com.fz.service.MailService;
import com.fz.service.TPermissionService;
import com.fz.service.TUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fz.util.JwtUtil;
import com.fz.vo.LoginVO;
import com.fz.vo.ResultVo;
import io.minio.errors.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author fz
 * @since 2024-08-15
 */
@Service
public class TUserServiceImpl extends ServiceImpl<TUserMapper, TUser> implements TUserService {
    @Resource
    TUserService tUserService;
    @Resource
    TPermissionService permissionService;
    @Resource
    PasswordEncoder passwordEncoder;
    @Resource
    UploadFileServiceImpl uploadFileService;
    @Resource
    private MailService mailService;
    @Resource
    private RedisTemplate<String, String> redisTemplate;


    @Override
    public TUser login(String phone, String password) {
        QueryWrapper<TUser> wrapper=new QueryWrapper<>();
        wrapper.eq("phone",phone);
        TUser user = this.getOne(wrapper);
        System.out.println("获得的密码"+user.getPassword()+"和"+password);
        if(null == user) {
            throw new FzException("用户不存在");
        }
        else if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new FzException("用户名或密码错误");
        }
        if(!user.getStatus()) {
            throw new FzException("管理员已经禁用,无法登录");
        }
        return user;
    }

    @Override
    public Boolean check(Long id,String field, String value) {
        QueryWrapper<TUser> wrapper = new QueryWrapper<>();
        wrapper.eq(field,value);
        if (null != id) {
            wrapper.ne("id", id);
        }
        return this.count(wrapper)==0;
    }

    @Override
    public Boolean update(Long id, String username, String nickName, Integer gender, Integer age,String phone, String email, MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        TUser user=new TUser(
                id,
                username,
                nickName,
                gender,
                age,
                phone,
                email
        );
        if(null!=file){
            user.setAvatar(uploadFileService.upload("images",file));
        }
        return this.updateById(user);
    }

    @Override
    public Boolean sendVerificationCode(String email) {
        String code = UUID.randomUUID().toString().substring(0, 4);
        String subject = "邮箱验证码";
        String text = "<h2>尊敬的用户<h2>" +
                "<p>您正在使用邮箱收取验证码</p>" +
                "<p>您的验证码是:" + code + "</p>";
        try {
            String existingCode = redisTemplate.opsForValue().get(email);
            if (existingCode != null) {
                throw new FzException("验证码已发送,请稍后再试");
            }
            mailService.send(email, subject, text);
            redisTemplate.opsForValue().set(email, code);
            return true;
        } catch (MessagingException e) {
            return false;
        }
    }

    @Override
    public Boolean verifyCode(String email, String code) {
        String storedCode = redisTemplate.opsForValue().get(email);
        if(code.equals(storedCode)){
            redisTemplate.delete(email);
            return true;
        }
        throw new FzException("验证码错误,请重新输入");
    }

    @Override
    public Boolean resetPassword(String email, String password) {
        QueryWrapper<TUser> wrapper = new QueryWrapper<>();
        wrapper.eq("email", email);
        String encodedPassword = passwordEncoder.encode(password);
        TUser user = this.getOne(wrapper);
        if(null == user) {
            throw new FzException("用户不存在");
        }
        if (passwordEncoder.matches(password, user.getPassword())) {
            throw new FzException("新密码不能与旧密码相同");
        }
        user.setPassword(encodedPassword);
        return this.updateById(user);
    }



    @Override
    public List<TUser> getList() {
        QueryWrapper<TUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1);
        return this.list(queryWrapper);
    }

    @Override
    public boolean del(long id, boolean status) {
        return this.updateById(new TUser(id,status));
    }


    @Override
    public Boolean transfer(Long id, String tophone, BigDecimal transferAmount) {
        TUser user = this.getById(id);
        QueryWrapper<TUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", tophone);
        TUser toUser = this.getOne(queryWrapper);
        if (user == null || toUser == null) {
            throw new FzException("用户不存在");
        }
        if (user.getAccount().compareTo(transferAmount)<0) {
            throw new FzException("余额不足");
        }
        user.setAccount(user.getAccount().subtract(transferAmount));
        toUser.setAccount(toUser.getAccount().add(transferAmount));
        return this.updateById(user) && this.updateById(toUser);
    }


    public Boolean recharge(Long id, BigDecimal rechargeAmount) {
        TUser user = this.getById(id);
        if (user == null) {
            throw new FzException("用户不存在");
        }
        user.setAccount(user.getAccount().add(rechargeAmount));
        return this.updateById(user);
    }
    public Boolean setProperty(Long id, String field, String value) {
        TUser user = this.getById(id);
        if (user == null) {
            throw new FzException("用户不存在");
        }
        UpdateWrapper<TUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id).set(field, value);
        return update(user, updateWrapper);

    }

    public Boolean payCheck(Long id, String password,BigDecimal paymoney) {
        QueryWrapper<TUser> wrapper=new QueryWrapper<>();
        System.out.println(id);
        System.out.println(paymoney);
        wrapper.eq("id",id);
        TUser user = this.getOne(wrapper);
//        if (user.getAccount().compareTo(paymoney)<0) {
//            throw new FzException("余额不足");
//        }else {
            if (!passwordEncoder.matches(password, user.getPassword())) {
                System.out.println("密码错误");
                throw new FzException("密码错误");
            }
            else {
                user.setAccount(user.getAccount().subtract(paymoney));
            }
        //}
        System.out.println("正确。。。。");
        return this.updateById(user);
    }
//    public Boolean payif(Long id, BigDecimal paymoney) {
//        TUser user = this.getById(id);
//
//        if (user.getAccount().compareTo(paymoney)<0) {
//            throw new FzException("余额不足");
//        }
//        System.out.println("更新成功！！！");
//        user.setAccount(user.getAccount().subtract(paymoney));
//        return this.updateById(user);
//    }






    @Override
    public LoginVO Buslogin(String phone, String password){
        TUser user = validateLogin(phone,password);
        return new LoginVO(JwtUtil.generateToken(user), this.getResourceByUserId(user.getId()));
    }
    private TUser validateLogin(String phone, String password) {
        System.out.println("AAA");
        QueryWrapper<TUser> wrapper=new QueryWrapper<>();
        wrapper.eq("phone",phone);
        TUser user = this.getOne(wrapper);
        if(null == user) {
            throw new FzException("用户不存在");
        }
        else if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new FzException("用户名或密码错误");
        }
        if(null!=user&&!user.getStatus()) {
            throw new FzException("管理员已经禁用,无法登录");
        }
        return user;
    }
    public List<TPermission> getResourceByUserId(Long userId){
      // return permissionService.getByUserId(userId) ;

        List<TPermission> menu = new ArrayList<>();
        Set<String> backUrls = new HashSet<>();
        List<TPermission> source = permissionService.getByUserId(userId);
        for (TPermission permissionService : source) {
            if (permissionService.getType().intValue() == 1) {
                if (permissionService.getParentId().intValue() == 0) {
                    menu.add(permissionService);
                } else {
                    for (TPermission parent : source) {
                        if (parent.getId().intValue() == permissionService.getParentId().intValue()){
                            List<TPermission> children = parent.getChildren();
                            if (null == children) {
                                children = new ArrayList<>();
                                parent.setChildren(children);
                            }
                            children.add(permissionService);
                            break;
                        }
                    }
                }
            }
            if(StringUtils.isNoneBlank(permissionService.getPath())) {
                String[] backs = permissionService.getPath().split("\\,");
                for (String url : backs) {
                    backUrls.add(url.trim());
                }
            }
        }
        redisTemplate.opsForValue().set("user::" + userId + "::resource", backUrls.toString(), 30, TimeUnit.MINUTES);
        return menu;
    }
    @Override
    public String getUsernameById(Long id){
        TUser user=this.getById(id);
        if(user!=null){
            return user.getUsername();
        }else{
            System.out.println("无效用户id，用户为空");
            return null;
        }
    }

}
